package com.giscloud.commons.utils;


import com.giscloud.commons.codec.AESUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * cookie工具类
 */
public class CookieUtils {
    protected final static Logger log = LoggerFactory.getLogger(CookieUtils.class);
    // 默认缓存时间,单位/秒, 2H
    private static final int COOKIE_MAX_AGE = 60 * 60 * 2;
    // 保存路径,根路径
    private static final String COOKIE_PATH = "/";
    /**
     * 获取当前请求所有cookie
     *
     * @return
     */
    public static Cookie[] getCookies(HttpServletRequest request) {
        return request.getCookies();
    }
    public static Cookie[] getCookies() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Cookie[] cookies = request.getCookies();
        return cookies;
    }

    /**
     * 添加cookie
     * @param name
     * @param value
     * @param domain
     * @param maxAge
     */
    public static void addCookie(String name, Object value,String domain,int maxAge) {
        try {
            String v = "";
            if(value instanceof String){
                v = (String) value;
            }else{
                v = FastJsonUtils.toJSONString(value);
            }
            Cookie cookie = new Cookie(name, v);
            cookie.setPath("/");
            cookie.setDomain(domain);
            cookie.setMaxAge(maxAge);
            saveCookie(cookie);
        } catch (Exception e) {
            log.error("添加cookie 失败" + e.getMessage());
        }
    }

    /**
     * 获取cookie
     *
     * @param name
     * @param clazz
     * @return
     */
    public static <T> T getCookie(String name, Class<T> clazz) {
        try {
            Cookie[] cookies = getCookies();
            String v = null;
            for (int i = 0; i < (cookies == null ? 0 : cookies.length); i++) {
                if ((name).equalsIgnoreCase(cookies[i].getName())) {
                    v = cookies[i].getValue();
                }
            }
            if (v != null) {
                return FastJsonUtils.toBean(v, clazz);
            }
        } catch (Exception e) {
            log.error("获取 clazz Cookie 失败" + e.getMessage());
        }
        return null;
    }

    /**
     * 获取cookie
     *
     * @param name
     * @return
     */
    public static String getCookie(String name) {
        try {
            Cookie[] cookies = getCookies();
            for (int i = 0; i < (cookies == null ? 0 : cookies.length); i++) {
                if ((name).equalsIgnoreCase(cookies[i].getName())) {
                    return cookies[i].getValue();
                }
            }
        } catch (Exception e) {
            log.error("获取String cookie 失败" + e.getMessage());
        }
        return null;
    }

    /**
     * 删除cookie
     *
     * @param name
     */
    public static void removeCookie(String name) {
        try {
            Cookie[] cookies = getCookies();
            for (int i = 0; i < (cookies == null ? 0 : cookies.length); i++) {
                if ((name).equalsIgnoreCase(cookies[i].getName())) {

                    Cookie cookie = new Cookie(name, "");
                    cookie.setPath("/");
                    cookie.setMaxAge(0);// 设置保存cookie最大时长为0，即使其失效
                    saveCookie(cookie);
                }
            }
        } catch (Exception e) {
            log.error("删除cookie失败" + e.getMessage());
        }
    }
    public static void saveCookie(Cookie cookie) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = attributes.getResponse();
        response.addCookie(cookie);
    }
    /**
     * 获取指定name的cookie
     *
     * @param name
     * @param request
     * @return
     */
    public static Cookie getCookie(String name, HttpServletRequest request) {
        Cookie[] cookies = getCookies(request);
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (name.equals(cookie.getName())) {
                    return cookie;
                }
            }
        }
        return null;
    }

    /**
     * 获取指定name的cookie值
     *
     * @param name
     * @param request
     * @return
     */
    public static String getCookieValue(String name, HttpServletRequest request) {
        Cookie[] cookies = getCookies(request);
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (name.equals(cookie.getName())) {
                    //必须使用HttpOnly属性来防止Cookie被JavaScript读取,从而避免跨站脚本攻击（XSS攻击）
                    //cookie.setHttpOnly(true);
                    return cookie.getValue();
                }
            }
        }
        return null;
    }


    /**
     * 新增cookie
     *
     * @param cookie   需要保存的cookie
     * @param response 响应对象
     */
    public static void addCookie(Cookie cookie, HttpServletResponse response) {
        response.addCookie(cookie);
    }

    /**
     * 新增cookie
     * <p/>
     *
     * @param response
     * @param name
     * @param value
     * @param maxAge   不设置过期时间就是会话
     * @param path     这个路径即该工程下都可以访问该cookie 如果不设置路径，那么只有设置该cookie路径及其子路径可以访问
     */
    public static void addCookie(HttpServletResponse response, String name, String value, Integer maxAge, String path) {
        Cookie cookie = new Cookie(name, value);
        if (maxAge != null) {
            cookie.setMaxAge(maxAge);
        }
        //必须使用HttpOnly属性来防止Cookie被JavaScript读取,从而避免跨站脚本攻击（XSS攻击）
        cookie.setHttpOnly(true);
        cookie.setPath(path);
        response.addCookie(cookie);
    }
    public static Cookie getCookieByName(HttpServletRequest request, String name){
        Map<String,Cookie> cookieMap = ReadCookieMap(request);
        if(cookieMap.containsKey(name)){
            Cookie cookie = (Cookie)cookieMap.get(name);
            return cookie;
        }else{
            return null;
        }
    }

    public  static Map<String,Cookie> ReadCookieMap(HttpServletRequest request){
        Map<String,Cookie> cookieMap = new HashMap<String,Cookie>();
        Cookie[] cookies = request.getCookies();
        if(null!=cookies){
            for(Cookie cookie : cookies){
                cookieMap.put(cookie.getName(), cookie);
            }
        }
        return cookieMap;
    }
    public static Cookie editCookie(HttpServletRequest request, String name, String value, Integer maxAge, String path){
        Cookie cookie = getCookieByName(request,name);
        if(cookie!=null) {
            cookie.setValue(value);
            cookie.setPath(path);
            cookie.setMaxAge(maxAge);
        }else {
            cookie= new Cookie(name.trim(), value.trim());
            cookie.setMaxAge(maxAge);
            cookie.setPath(path);
        }
        return cookie;
    }
    /**
     * 新增cookie
     * <p/>
     *
     * @param response
     * @param name
     * @param value
     * @param domain
     * @param maxAge   不设置过期时间就是会话
     * @param path     这个路径即该工程下都可以访问该cookie 如果不设置路径，那么只有设置该cookie路径及其子路径可以访问
     */
    public static void addCookie(HttpServletResponse response, String name, String value, String domain, Integer maxAge, String path) {
        Cookie cookie = new Cookie(name, value);
        cookie.setDomain(domain);
        if (maxAge != null) {
            cookie.setMaxAge(maxAge);
            //cookie.setHttpOnly(false);
        }
        cookie.setPath(path);
        response.addCookie(cookie);
    }

    /**
     * 新增cookie
     *
     * @param response
     * @param name
     * @param value
     * @param domain
     * @param maxAge
     * @param isHttpOnly
     */
    public static void addCookie(HttpServletResponse response, String name, String value, String domain,
                                 Integer maxAge, boolean isHttpOnly, String path) {
        Cookie cookie = new Cookie(name, value);
        cookie.setDomain(domain);
       // cookie.setHttpOnly(isHttpOnly);
        if (maxAge != null) {
            cookie.setMaxAge(maxAge);
        }
        cookie.setPath(path);
        response.addCookie(cookie);
    }

    public static void addCookie(HttpServletResponse response, String name, String value, String domain,
                                 Integer maxAge, boolean isHttpOnly, String path, boolean isSecure) {
        Cookie cookie = new Cookie(name, value);
        cookie.setDomain(domain);
       // cookie.setHttpOnly(isHttpOnly);
        if (maxAge != null) {
            cookie.setMaxAge(maxAge);
        }
        cookie.setPath(path);
        cookie.setSecure(isSecure);
        response.addCookie(cookie);
    }

    public static String decodeCookie(HttpServletRequest request, String key, String password) {
        // 判断cookie中的值
        Cookie[] cookies = getCookies(request);
        if (cookies == null) {
            return null;
        }
        String cookieStr = null;
        // cookiename是否失效
        String cookieValue = CookieUtils.getCookieValue(key, request);
        if (StringUtils.isNotEmpty(cookieValue)) {
            cookieStr = AESUtils.decrypt2str(cookieValue, password);
            if (StringUtils.isEmpty(cookieStr)) {
                return null;
            }
        } else {
            return null;
        }
        return cookieStr;
    }

    /**
     * 删除cookies
     * <p/>
     *
     * @param request
     * @param response
     * @param name
     * @param path     必须设置，否则无效
     */
    public static String deleteCookie(HttpServletRequest request, HttpServletResponse response, String name, String path) {
        String value = null;
        Cookie[] cookies = getCookies(request);
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (name.equals(cookie.getName())) {
                    value = cookie.getValue();
                    cookie.setMaxAge(0);
                    cookie.setPath(path);
                    response.addCookie(cookie);
                }
            }
        }
        return value;
    }

    /**
     * 删除cookie
     *
     * @param cookie   需要删除的某个cookie
     * @param response 响应对象
     * @param domain
     * @param path
     */
    public static void deleteCookie(Cookie cookie, HttpServletResponse response, String domain, String path) {
        if (cookie != null) {
            cookie.setMaxAge(0);
            cookie.setValue(null);
            cookie.setPath(path);
            cookie.setDomain(domain);
            response.addCookie(cookie);
        }
    }
    public static void deleteCookie(HttpServletResponse httpServletResponse, String name) {
        Cookie cookie = new Cookie(name, null);
        cookie.setPath("/");
        //cookie.setHttpOnly(true);
        cookie.setMaxAge(0);
        cookie.setDomain("localhost");
        httpServletResponse.addCookie(cookie);
    }

    public  static void deleteCookie(HttpServletResponse httpServletResponse, String name, String domain) {
        Cookie cookie = new Cookie(name, null);
        cookie.setPath("/");
        //cookie.setHttpOnly(true);
        cookie.setMaxAge(0);
        cookie.setDomain(domain);
        httpServletResponse.addCookie(cookie);
    }
    public static Cookie delCookie(HttpServletRequest request, String name, String path){
        Cookie cookie = getCookieByName(request,name);
        cookie.setValue(null);
        cookie.setMaxAge(0);// 立即销毁cookie
        cookie.setPath(path);
        return cookie;
    }
    /**
     * 得到cookie的域名
     */
    private static final String getDomainName(HttpServletRequest request) {
        String domainName = null;

        String serverName = request.getRequestURL().toString();
        if (serverName == null || serverName.equals("")) {
            domainName = "";
        } else {
            serverName = serverName.toLowerCase();
            serverName = serverName.substring(7);
            final int end = serverName.indexOf("/");
            serverName = serverName.substring(0, end);
            final String[] domains = serverName.split("\\.");
            int len = domains.length;
            if (len > 3) {
                // www.xxx.com.cn
                domainName = "." + domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
            } else if (len <= 3 && len > 1) {
                // xxx.com or xxx.cn
                domainName = "." + domains[len - 2] + "." + domains[len - 1];
            } else {
                domainName = serverName;
            }
        }

        if (domainName != null && domainName.indexOf(":") > 0) {
            String[] ary = domainName.split("\\:");
            domainName = ary[0];
        }
        return domainName;
    }

    /**
     * 保存
     *
     * @param response
     * @param key
     * @param value
     * @param ifRemember
     */
    public static void set(HttpServletResponse response, String key, String value, boolean ifRemember) {
        int age = ifRemember?COOKIE_MAX_AGE:-1;
        set(response, key, value, null, COOKIE_PATH, age, true);
    }

    /**
     * 保存
     *
     * @param response
     * @param key
     * @param value
     * @param maxAge
     */
    private static void set(HttpServletResponse response, String key, String value, String domain, String path, int maxAge, boolean isHttpOnly) {
        Cookie cookie = new Cookie(key, value);
        if (domain != null) {
            cookie.setDomain(domain);
        }
        cookie.setPath(path);
        cookie.setMaxAge(maxAge);
        cookie.setHttpOnly(isHttpOnly);
        response.addCookie(cookie);
    }

    /**
     * 查询value
     *
     * @param request
     * @param key
     * @return
     */
    public static String getValue(HttpServletRequest request, String key) {
        Cookie cookie = get(request, key);
        if (cookie != null) {
            return cookie.getValue();
        }
        return null;
    }

    /**
     * 查询Cookie
     *
     * @param request
     * @param key
     */
    private static Cookie get(HttpServletRequest request, String key) {
        Cookie[] arr_cookie = request.getCookies();
        if (arr_cookie != null && arr_cookie.length > 0) {
            for (Cookie cookie : arr_cookie) {
                if (cookie.getName().equals(key)) {
                    return cookie;
                }
            }
        }
        return null;
    }

    /**
     * 删除Cookie
     *
     * @param request
     * @param response
     * @param key
     */
    public static void remove(HttpServletRequest request, HttpServletResponse response, String key) {
        Cookie cookie = get(request, key);
        if (cookie != null) {
            set(response, key, "", null, COOKIE_PATH, 0, true);
        }
    }

}
